package com.lej.app_main.unity

import android.Manifest
import android.content.ContentValues
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.KeyEvent
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.activity.result.ActivityResultLauncher
import androidx.lifecycle.lifecycleScope
import com.alibaba.android.arouter.facade.annotation.Route
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.lej.app_main.BuildConfig
import com.lej.app_main.R
import com.lej.app_main.mainService
import com.lej.app_main.unity.pay.U3DConst
import com.lej.app_main.unity.pay.UnityPayActivity
import com.lej.app_main.webJs.HomeJavascriptInterface
import com.lej.core.common.*
import com.lej.core.dsl.*
import com.lej.core.permission.reqPermission
import com.lej.core.router.CRouter
import com.lej.core.utils.ConvertUtils
import com.lej.core.utils.KLog
import com.lej.core.utils.ToastUtils
import com.lej.core.utils.extention.*
import com.lej.core.utils.urlToBitmap
import com.lej.core.webView.WebViewFragment
import com.lej.core.webView.jsInstances
import com.lej.dataservice.club.bean.main.recorder.SpeechData
import com.lej.dataservice.club.bean.main.unity.AndroidParams
import com.lej.dataservice.club.bean.main.unity.MatchResInfo
import com.lej.dataservice.club.bean.main.unity.UGoodsInfo
import com.lej.dataservice.club.bean.main.unity.UnityMiniGameFrom
import com.lej.dataservice.club.bean.share.ShareRequest
import com.lej.dataservice.club.http.REMOTE_LOGIN
import com.lej.dataservice.club.http.base.toBody
import com.lej.dataservice.club.http.checkData
import com.lej.player.RTMPAudioPlayer
import com.lej.wx.shareSmallApp
import com.permissionx.guolindev.PermissionX
import com.lej.wx.wxShareImg
import com.tencent.cloud.qcloudasrsdk.recognizer.QCloudOneSentenceRecognizer
import com.tencent.cloud.qcloudasrsdk.recognizer.QCloudOneSentenceRecognizerListener
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import java.util.*

/**
 *  author: cjq
 *  date  : 2022/4/22 0022
 *  desc  :
 */
@Route(path = CRouter.unityhouse)
class UnityRoomActivity : UnityPlayerActivity(), QCloudOneSentenceRecognizerListener {
    private var data: AndroidParams? = null

    private var resPayLauncher: ActivityResultLauncher<Intent>? = null

    private var recognizer: QCloudOneSentenceRecognizer? = null
    private var recording = false
    private var resultText = ""
    private var unityEvent: AndroidEventToUnity? = null

    private var audioPlayer: RTMPAudioPlayer? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(mUnityPlayer.view)
        setContentView(R.layout.appmain_activity_unity_room)
        jsInstances.add(::HomeJavascriptInterface)
        findViewById<FrameLayout>(R.id.fl_unity_container).addView(mUnityPlayer.view)
//        addLoadingView()
        registerLauncher()
        recognizer ?: initQCloudOneSentenceRecognizer()
        initData()

        //test code
//        JumpUnity(RTMPAudioInit, "rtmp://stream.dayou.cloud/live/1")
//        JumpUnity(StartSound, null)
    }

    private fun initData() {
        val fromType = intent.getIntExtra(UnityRoomType, UnityMiniGameFrom.ENTER_HOUSE)
        val romeRoomId = intent.getIntExtra(UnityRoomId, 0)
        if (romeRoomId <= 0 && fromType == UnityMiniGameFrom.ENTER_HOUSE) {
            "房间信息错误,请重试".toast()
            finish()
            return
        }
        data = AndroidParams(fromType = fromType, romeRoomId = romeRoomId)
        if (fromType == UnityMiniGameFrom.ENTER_SHOP_PAGE) {
            data?.goodsInfo = UGoodsInfo(
                shopType = intent.getStringExtra(UnityRoomShopType),
                shopId = intent.getIntExtra(UnityRoomShopId, 0),
                goodsId = intent.getIntExtra(UnityRoomGoodsId, 0),
                isAvatar = intent.getBooleanExtra(UnityRoomIsAvatar, false)
            )
        } else if (fromType == UnityMiniGameFrom.VISITING_CARD_PAGE) {
            data?.targetUid = intent.getIntExtra(UnityTargetUid, 0)
        }
        data?.toJson()?.logD("sss")
    }

    private fun addLoadingView() {
        (window.decorView as? ViewGroup)?.ImageView {
            id = R.id.appmain_loading_view
            layout_width = match_parent
            layout_height = match_parent
            src = R.drawable.bg_unity_loading
            scaleType = scale_center_crop
        }
    }


    //注意,此回调在子线程触发,涉及ui操作需要切换到主线程
    fun JumpUnity(key: Int, json: String?) {
        runCatching {
            when (key) {
                SynUserInfo -> setTextParams()
                ClickBack -> androidBack()
                ClickNftDetail -> androidDetail(json)
                ClientShare -> androidShare(json)
                ClickNftCollect -> androidDetail(json)
                //CloseLoading -> hideLoading()
                StartRecorder -> startRecorder()
                StopRecorder -> stopRecorder()
                showMatchDialog -> showMatchDialog(json)
                RemoteLogin -> toLogin()
                RechargeCurrency -> orderWxPay(json)
                RTMPAudioInit -> json?.audioInit()
                StartSound -> audioPlayer?.start()
                HideSound -> audioPlayer?.pause()
                NativeCloseLoading -> closeView()
                ScanFileToPic -> scanFileToPic(json)
                ShowWebAct -> showWebAct(json)
                PermissionReq -> runCatching { rePermission(json) }
                CheckPermReq -> checkPermission(json)
                SharePic -> sharePic(json)
                else -> {}
            }
        }.onFailure {
            KLog.e("--------JumpUnity error------\n" + it.message)
        }
    }

    private fun showWebAct(json: String?) {
        val asJson = json?.fromJson<JsonObject>() ?: return
        val urlWeb = asJson.get("webUrl").asString
        addFragment(R.id.fl_container, WebViewFragment(), FRAGMENT_WEB_TAG) {
            putString(WEB_URL, urlWeb)
            putBoolean(WEB_SHOW_TITLE, false)
        }
    }

    /**
     * 分享图片
     */
    private fun sharePic(json: String?) {
        val byteData = getJsonByte(json = json) ?: return
        wxShareImg(byteData)
    }

    /**
     * 保存图片到相册
     */
    private fun scanFileToPic(json: String?) {
        val byteData = getJsonByte(json = json) ?: return
        val bitmap = BitmapFactory.decodeByteArray(byteData, 0, byteData.size)
        val uri = contentResolver.insert(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            ContentValues()
        ) ?: return
        contentResolver.openOutputStream(uri).use {
            if (bitmap.compress(Bitmap.CompressFormat.JPEG, 90, it)) {
                "保存成功".toast()
            } else {
                "保存失败".toast()
            }
        }
    }


    private fun getJsonByte(json: String?): ByteArray? {
        val asJson = json?.fromJson<JsonObject>() ?: return null
        val picBase64Str = asJson.get("base64").asString
        picBase64Str ?: return null
        return Base64.getDecoder().decode(picBase64Str)
    }

    //抢登,去登录页面
    private fun toLogin() {
        router(CRouter.login) { addClearFlag();withInt(ERROR_CODE, REMOTE_LOGIN) }
    }

    private fun closeView() {
        //关闭弹窗
        val img = findViewById<ImageView>(R.id.appmain_loading_view) ?: return
        lifecycleScope.launch {
            (window.decorView as? ViewGroup)?.removeView(img)
        }
    }

    private fun String.audioInit() {
        val url = this.toJson()
        audioPlayer = audioPlayer?.changeUrl(url)
            ?: RTMPAudioPlayer(this@UnityRoomActivity, url)
    }

    fun SetupEventHandler(handler: AndroidEventToUnity) {
        unityEvent = handler
    }

    private fun startRecorder() {
        lifecycleScope.launch {
            if (reqPermission(Manifest.permission.RECORD_AUDIO)) {
                runCatching {
                    Log.d("语音识别", "语音识别进入")
                    recognizer?.setDefaultParams(0, 0, 1, 1, null, null)
                    recognizer?.recognizeWithRecorder()
                    recognizer?.setQCloudOneSentenceRecognizerAudioPathListener { audioPath -> }
                }.onFailure { e ->
                    Log.d("语音识别", "${e.message}")
                }
            }
        }
    }

    private fun stopRecorder() {
        if (recording) {
            Log.d("语音识别", "语音退出")
            recognizer?.stopRecognizeWithRecorder()
        }
    }

    private fun rePermission(json: String?) {
        val asJson = json?.fromJson<JsonObject>() ?: return
        val code = asJson.get("code").asInt

        val per = when (code) {
            U3DConst.REQ_AUDIO_TEAM -> arrayOf(Manifest.permission.RECORD_AUDIO)
            else -> return
        }
        lifecycleScope.launch {
            val allGranted = reqPermission(*per)
            PermissionRes.eventU3d("hasPermission" to allGranted, "code" to code)
        }
    }

    private fun checkPermission(json: String?) {
        val asJson = json?.fromJson<JsonObject>() ?: return
        val code = asJson.get("code").asInt
        val per = when (code) {
            U3DConst.REQ_AUDIO_TEAM -> Manifest.permission.RECORD_AUDIO
            else -> return
        }
        val allGranted = PermissionX.isGranted(this, per)
        CheckPermRes.eventU3d("hasPermission" to allGranted, "code" to code)
    }

    /**
     * 传递token等参数
     */
    private fun setTextParams() {
        unityEvent?.OnAndroidEvent(SynUserInfo, data?.toJson() ?: "")
    }

    /**
     * 返回
     */
    private fun androidBack() {
        finish()
    }

    /**
     * unity点击头像回个人中心
     */
    fun androidToCenter(str: String) {
        ToastUtils.show("点击头像")
    }

    /**
     * unity点击我想要个空间
     */
    fun androidGetHouse(str: String) {
        ToastUtils.show("点击我想要个空间")
    }

    /**
     * 分享
     *  type = 1  逛空间  roomId
     *  type = 2  转让空间 transferId
     */
    fun androidShare(json: String?) {
        MainScope().launch {
            runCatching {
                val jsonObj = JsonParser.parseString(json).asJsonObject
                val transferId = jsonObj.get("transferId").asString
                val type = jsonObj.get("type")?.asString
                val shareType = type!!.toInt()
                val wxShareInfo = mainService.shareInfo(
                    ShareRequest(
                        shareType,
                        if (shareType == 1) transferId else "",
                        "",
                        if (shareType != 1) transferId else ""
                    ).toBody()
                ).checkData()

                val url = "${wxShareInfo.thumbData}?imageView2/1/w/400/h/320"
                val id = if (shareType == 2) "transferID" else "id"
                val bitmap = this@UnityRoomActivity.urlToBitmap(url) ?: return@launch
                val urlByte = ConvertUtils.bitmap2Bytes(bitmap, Bitmap.CompressFormat.JPEG)
                wxShareInfo.urlData = urlByte
                wxShareInfo.miniprogramType = 2
                wxShareInfo.path = "pages/index/index?$id=$transferId&type=$type"
                shareSmallApp(wxShareInfo)
            }.onFailure {
                Log.d("HAHAHA", "androidShare ${it.message}")
            }
        }
    }

    /**
     * 跳转详情，去购买
     */
    private fun androidDetail(json: String?) {
//        runCatching {
//            val jsonObj = JsonParser.parseString(json).asJsonObject
//            val nftId = jsonObj.get("nftId")?.asInt ?: return
//            router(CRouter.nftDetail) { withInt(Params.NFT_ID, nftId) }
//        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            finish()
        }
        Log.d("HAHAHA", "*****&$$$$******")
        return super.onKeyDown(keyCode, event)
    }

    private fun initQCloudOneSentenceRecognizer() {
        recognizer = QCloudOneSentenceRecognizer(
            this,
            BuildConfig.TENCENT_VOICE_APP_ID,
            BuildConfig.TENCENT_VOICE_APP_SERCERT,
            BuildConfig.TENCENT_VOICE_APP_SERCERT_KEY
        )
        recognizer?.setCallback(this)
    }

    override fun didStartRecord() {
        Log.d("语音识别", "语音识别Android开始录音")
        recording = true
        resultText = ""
    }

    override fun didStopRecord() {
        Log.d("语音识别", "语音识别Android停止录音")
        recording = false
    }

    override fun recognizeResult(
        recognizer: QCloudOneSentenceRecognizer?,
        result: String?,
        e: Exception?
    ) {
        Log.d("语音识别", "Android 结果\nresult$result\nexception${e?.message}")
        try {
            if (result.isNullOrEmpty()) {
                resultText = "语音识别Android未识别到"
                unityEvent?.OnAndroidEvent(GetRecorderText, resultText)
                return
            }
            val response = result.fromJson<SpeechData>()
            resultText = response?.Response?.Result ?: "转换失败"
            resultText = resultText.ifEmpty { "转换失败" }

            unityEvent?.OnAndroidEvent(GetRecorderText, resultText)
        } catch (e: Exception) {
            Log.d("语音识别", "${e.message}")
        }
    }

    private fun showMatchDialog(json: String?) {
        val info = json?.fromJson<MatchResInfo>() ?: return
        CompositeResDialog.show(this, info)
    }

    private fun Int.eventU3d(vararg kv: Pair<String, Any>) {
        unityEvent?.OnAndroidEvent(this, mapOf(*kv).toJson())
    }

    //region 支付相关
    private fun registerLauncher() {
        resPayLauncher = registerIntent {
            if (it.resultCode == RESULT_OK) {
                val resCode = it.data?.getIntExtra(U3DConst.PAY_STATUS_KEY, U3DConst.WX_CANCEL)
                    ?: U3DConst.WX_ERROR
                payRes(resCode)
            }
        }
    }

    private fun orderWxPay(json: String?) {
        runCatching {
            val data = json?.fromJson<JsonObject>() ?: return
            val orderId = data.get(U3DConst.ORDER_ID).asInt
            val intent = Intent(this, UnityPayActivity::class.java)
            intent.putExtra(U3DConst.ORDER_ID, orderId)
            resPayLauncher?.launch(intent)
        }.onFailure {
            payRes(U3DConst.WX_ERROR)
        }
    }

    private fun payRes(payStatus: Int) {
        RechargeResult.eventU3d(U3DConst.PAY_STATUS_KEY to payStatus)
    }
    //endregion
}